#pragma once


/*
 * Networking functions for TCP and UDP sockets
 * Dependencies: bzbutil, winsock2 (Windows)
 */


#include <string>
#include <vector>


namespace bzbnet {


	constexpr int DEFAULT_BACKLOG = 10;

	constexpr unsigned int DEFAULT_PACKETSIZE = 512;


/*
 * Initializes the system library for networking
 * TCPSocket and UDPSocket call this function automatically.
 */

void initialize();


/*
 * Terminates the system library for networking
 */

void destroy();


/*
 * Returns a list of the associated IPs of the given hostname
 */

std::vector<std::string> get_host_ip_list(std::string hostname);


/*
 * Returns a list of the associated hostnames and IPs of the given hostname
 */

std::vector<std::string> get_host_list(std::string hostname);


/*
 * Returns the machine's hostname
 */
std::string get_hostname();


/*
 * Socket class for TCP networking
 */

class TCPSocket {
	private:
		void* fd;

	public:

		TCPSocket();

		TCPSocket(void* socket_fd);

		~TCPSocket();

		void connect(std::string hostname, std::string service);

		void connect(std::string hostname, uint16_t port);

		void bind(std::string hostname, std::string service);

		void bind(std::string hostname, uint16_t port);

		void bind(std::string service);

		void bind(uint16_t port);

		void listen(std::string service, int backlog = DEFAULT_BACKLOG);

		void listen(uint16_t port);

		TCPSocket accept();

		std::vector<char> recv(unsigned int packetsize = DEFAULT_PACKETSIZE);

		void send(std::string data);

		void send(std::vector<char> data);

		void close();

		bool is_open();

		int get_raw_fd();

};


/*
 * Socket class for UDP networking
 */

class UDPSocket {
	private:
		void* fd;

	public:

		UDPSocket();

		~UDPSocket();

		void connect(std::string hostname, std::string service);

		void connect(std::string hostname, uint16_t port);

		void bind(std::string hostname, std::string service);

		void bind(std::string hostname, uint16_t port);

		void bind(std::string service);

		void bind(uint16_t port);

		void listen(std::string service, int backlog = DEFAULT_BACKLOG);

		void listen(uint16_t port);

		std::vector<char> recvfrom();

		void sendto(std::string data, std::string hostname, std::string service);

		void sendto(std::string data, std::string hostname, uint16_t port);

		void sendto(std::vector<char> data, std::string hostname, std::string service);

		void sendto(std::vector<char> data, std::string hostname, uint16_t port);

		void close();

		bool is_open();

		int get_raw_fd();

};

}
